<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title></title>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }

        body, html {
            height: 100%;
            margin: 0;
            font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
            background: #000;
        }

        #chat {
            width: 100%;
            height: 100vh;
            display: flex;
            flex-direction: column;
        }

        #chat-messages {
            background: #111;
            flex-grow: 1;
            overflow-y: auto;
            padding: 20px;
            box-sizing: border-box;
        }

        #chat-input {
            display: flex;
            padding: 10px;
            background: #222;
        }

        #chat-input input[type="text"] {
            flex-grow: 1;
            padding: 10px 20px;
            border: 1px solid #c63c3c;
            border-radius: 5px;
            margin-right: 10px;
            color: white;
            background: #000;
            box-shadow: 0 0 5px #f00;
            transition: background-color 0.2s, box-shadow 0.2s;
            outline: none;
            font-size: 1.2em;
        }

        #chat-input input[type="text"]:hover {
            background-color: #222;
            border: 1px solid #c63c3c;
            box-shadow: 0 0 10px #f14848;
        }

        #chat-input input[type="submit"] {
            padding: 10px 10px;
            border: 1px solid #d23232;
            border-radius: 5px;
            background-color: #c63c3c;
            color: #fff;
            cursor: pointer;
            box-shadow: 0 0 10px red;
            transition: background-color 0.2s, transform 0.2s, box-shadow 0.2s;
        }

        #chat-input input[type="submit"]:hover {
            background-color: #c63c3c;
            box-shadow: 0 0 15px #f00;
            transform: scale(1.05);
        }

        @keyframes flipIn {
            from {
                transform: rotateX(-90deg);
                opacity: 0;
            }
            to {
                transform: rotateX(0deg);
                opacity: 1;
            }
        }

        .message {
            border-left: 2px solid #c63c3c;
            animation: flipIn 0.3s ease-out;
            background-color: #1d1d1d;
            border-radius: 0 10px 10px 0;
            padding: 8px 10px;
            margin: 10px 0;
            color: #c4b3b3;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
            position: relative; /* Needed for absolute positioning of the time */
        }

        .time {
            font-size: 0.8em;
            color: #888;
            position: absolute;
            top: 10px;
            right: 10px;
            margin-bottom: 5px;
        }

        .meta {
            font-size: 0.8em;
            color: #888;
            margin-top: 3px;
            margin-bottom: 5px;
            word-wrap: break-word;
            overflow-wrap: break-word;
            max-width: 90%;
        }

        .text {
            font-size: 1em;
            line-height: 1.5;
            word-wrap: break-word;
            overflow-wrap: break-word;
            max-width: 90%;
        }
    </style>
    <script type="text/javascript" src="https://unpkg.com/centrifuge@^5/dist/centrifuge.js"></script>
    <!--    <script type="text/javascript" src="https://unpkg.com/centrifuge@^5/dist/centrifuge.protobuf.js"></script>-->
    <script type="text/javascript">
        class Message {
            constructor(time, text, meta) {
                this.time = time; // The time the message was sent
                this.text = text; // The text of the message
                this.meta = meta; // Any additional data, like metadata or JSON content
            }

            // Method to convert the message to an HTML element
            toHtml() {
                const messageElement = document.createElement('div');
                messageElement.className = 'message';

                const timeElement = document.createElement('div');
                timeElement.className = 'time';
                timeElement.textContent = this.time;

                const textElement = document.createElement('div');
                textElement.className = 'text';
                textElement.textContent = this.text;

                messageElement.appendChild(timeElement);
                messageElement.appendChild(textElement);
                if (this.meta) {
                    const metaElement = document.createElement('div');
                    metaElement.className = 'meta';
                    metaElement.textContent = this.meta;
                    messageElement.appendChild(metaElement);
                }

                return messageElement;
            }
        }

        // helper functions to work with escaping html.
        const tagsToReplace = {'&': '&amp;', '<': '&lt;', '>': '&gt;'};

        function replaceTag(tag) {
            return tagsToReplace[tag] || tag;
        }

        function safeTagsReplace(str) {
            return str.replace(/[&<>]/g, replaceTag);
        }

        const channel = "chat:index";

        window.addEventListener('load', function () {
            const messages = document.getElementById('chat-messages');
            const inputContainer = document.getElementById("chat-input");
            const input = document.getElementById("chat-text");
            const submit = document.getElementById('chat-submit');

            const data = {
                data: {
                    token: "15519549175",
                    platformID: 5,
                    operationID: "20241028"
                }
            };

            const centrifuge = new Centrifuge('ws://localhost:10001/connection/websocket', data);

            centrifuge.on('connecting', function (ctx) {
                drawText('🚧 Connecting', JSON.stringify(ctx));
                input.setAttribute('disabled', 'true');
            });

            centrifuge.on('disconnected', function (ctx) {
                drawText('⭕ Disconnected', JSON.stringify(ctx));
                input.setAttribute('disabled', 'true');
            });

            // bind listeners on centrifuge object instance events.
            centrifuge.on('connected', function (ctx) {
                drawText('✅ Connected', JSON.stringify(ctx));
                input.removeAttribute('disabled');
            });

            centrifuge.on('message', function (ctx) {
                drawText('Message received', JSON.stringify(ctx.data));
            });

            centrifuge.on('publication', function (ctx) {
                drawText('📟 Server-side publication from channel ' + ctx.channel, JSON.stringify(ctx.data));
            });

            centrifuge.on('join', function (ctx) {
                drawText('➡️ Server-side join from channel ' + ctx.channel, JSON.stringify(ctx.info));
            });

            centrifuge.on('leave', function (ctx) {
                drawText('⬅️ Server-side leave from channel ' + ctx.channel, JSON.stringify(ctx.info));
            });

            centrifuge.on('subscribing', function (ctx) {
                drawText('🚧 Subscribing on server-side channel ' + ctx.channel);
            });

            centrifuge.on('unsubscribed', function (ctx) {
                drawText('⭕ Unsubscribed from server-side channel ' + ctx.channel);
            });

            centrifuge.on('subscribed', function (ctx) {
                drawText('✅ Subscribed to server-side channel ' + ctx.channel, JSON.stringify(ctx));
            });

            // show how many users currently in channel.
            function showPresence(sub) {
                sub.presence().then(function (result) {
                    let count = 0;
                    for (let key in result.clients) {
                        count++;
                    }
                    drawText('🟢 Now in this room – ' + count + ' clients');
                }, function (err) {
                    drawText("❌️ Presence error", JSON.stringify(err));
                });
            }

            // subscribe on channel and bind various event listeners. Actual
            // subscription request will be sent after client connects to
            // a server.
            const sub = centrifuge.newSubscription(channel, {});

            sub.on("publication", handlePublication)
                .on("join", handleJoin)
                .on("leave", handleLeave)
                .on("unsubscribed", handleUnsubscribed)
                .on("subscribed", handleSubscribed)
                .on("subscribing", handleSubscribing)
                .on("error", handleSubscriptionError);

            // sub.subscribe();

            // Trigger actual connection establishing with a server.
            // At this moment actual client work starts - i.e. subscriptions
            // defined start subscribing etc.
            centrifuge.connect();

            function handleSubscribed(ctx) {
                drawText('✅ Subscribed on channel ' + ctx.channel, JSON.stringify(ctx));
                showPresence(sub);

                centrifuge.rpc("getCurrentYear", {}).then(function (data) {
                    drawText("✅ Got RPC response", JSON.stringify(data));
                }, function (err) {
                    drawText("❌️ Got RPC error", JSON.stringify(err));
                });
            }

            function handleUnsubscribed(ctx) {
                drawText('⭕ Unsubscribed from channel ' + ctx.channel, JSON.stringify(ctx));
            }

            function handleSubscribing(ctx) {
                drawText('🚧 Subscribing on channel ' + ctx.channel, JSON.stringify(ctx));
            }

            function handleSubscriptionError(ctx) {
                drawText('❌ Error subscribing on channel', JSON.stringify(ctx));
            }

            function handlePublication(ctx) {
                const inputText = ctx.data["input"].toString();
                const text = safeTagsReplace(inputText);
                drawText("📟 " + text, JSON.stringify(ctx));
            }

            function handleJoin(ctx) {
                drawText('➡️ Client joined channel ' + this.channel, JSON.stringify(ctx));
            }

            function handleLeave(ctx) {
                drawText('⬅️ Client left channel ' + this.channel, JSON.stringify(ctx));
            }

            function drawText(text, meta) {
                const message = new Message((new Date()).toLocaleTimeString(), text, meta);
                const needScroll = needScrollToBottom();
                messages.appendChild(message.toHtml());
                if (needScroll) {
                    messages.scrollTop = messages.scrollHeight;
                }
            }

            function needScrollToBottom() {
                return messages.scrollHeight - messages.scrollTop - messages.clientHeight - inputContainer.clientHeight <= 0;
            }

            function sendMessage() {
                // sub.publish({"input": input.value}).then(function () {
                //     console.log("Successfully published to channel");
                // }, function (err) {
                //     drawText("❌ Publish error", JSON.stringify(err));
                // });
                const rpcRequestData = {
                    reqIdentifier: 1001,
                    token: "123456",
                    sendID: "123456",
                    operationID: "123456",
                    msgIncr: "123456",
                    data: input.value
                };
                // const binary = new TextEncoder("utf-8").encode(JSON.stringify(rpcRequestData));

                centrifuge.rpc("GetSeq", rpcRequestData).then(function (data) {
                    drawText("✅ Got RPC response", JSON.stringify(data));
                }, function (err) {
                    drawText("❌️ Got RPC error", JSON.stringify(err));
                });
                input.value = '';
            }

            submit.addEventListener('click', function (event) {
                event.preventDefault();
                sendMessage();
            });

            input.addEventListener('keypress', function (e) {
                if (e.key === "Enter") {
                    e.preventDefault();
                    sendMessage();
                }
            });
        });
    </script>
</head>
<body>
<div id="chat">
    <div id="chat-messages"></div>
    <div id="chat-input">
        <input type="text" id="chat-text" placeholder="Type your message here..." autocomplete="off"/>
        <input type="submit" id="chat-submit" value="SEND"/>
    </div>
</div>
</body>
</html>
